Числа с плавающей точкой
Числа с плавающей запятой в руководстве называются «числами с плавающей точкой»,
поскольку в английском языке — языке оригинала PHP-руководства — целую и дробную часть в таких числах
разделяет точка, а не запятая. В других языках программирования числа с плавающей точкой называют также:
float, double или real. В PHP числа с плавающей точкой записывают следующими синтаксисами:
Поддержка подчёркиваний в числах появилась с PHP 7.4.0:
Размер числа с плавающей точкой зависит от платформы, хотя максимум обычного значения с плавающей точкой
составляет примерно 1.8e308 с точностью около 14 десятичных цифр (64-битный формат стандарта IEEE).
Внимание
Точность чисел с плавающей точкой
Точность чисел с плавающей точкой ограничена. Хотя точность
зависит от операционной системы, PHP обычно использует формат
двойной точности, который определяет стандарт IEEE 754, который даёт
максимальную относительную погрешность округления порядка 1.11e-16.
Неэлементарные арифметические операции иногда дают бо́льшие ошибки,
и, конечно, учитывают распространение ошибок при объединении операции.
Кроме того, рациональные числа наподобие 0.1
или 0.7
, которые легко точно представить
как числа с плавающей точкой по основанию 10 — в десятичной системе счисления,
внутренне невозможно точно представить как числа с плавающей точкой по основанию 2 — в двоичной системе счисления,
независимо от размера мантиссы. Поэтому такие числа невозможно преобразовать во внутреннюю двоичную форму
без небольшой потери точности. Иногда это даёт противоречивые результаты:
например, округление floor((0.1 + 0.7) * 10)
возвращает
значение 7
вместо 8
, которое ожидалось, поскольку
внутреннее представление будет примерно таким:
7.9999999999999991118...
.
Точности чисел с плавающей точкой не доверяют до последней цифры
и не сравнивают такие числа на предмет равенства.
Когда требуется повышенная точность, пользуются
функциями математики произвольной точности
и функциями математики множественной точности модуля GMP.
«Простое» объяснение даёт » руководство по числам с плавающей точкой,
которое также называется «Why don’t my numbers add up?» («Почему мои числа не складываются?» — англ.)
Преобразование в число с плавающей точкой
Из строк
Числовые строки
или строки с начальной числовой последовательностью преобразовываются в значение с плавающей точкой,
иначе строка преобразуется в целочисленное значение 0
.
Из других типов
При преобразовании значений других типов в число с плавающей точкой значение вначале преобразовывается в целое число (int),
а затем в число с плавающей точкой (float).
Дополнительную информацию о целочисленном преобразовании даёт раздел «Преобразование в целое число».
Замечание:
Поскольку поведение отдельных типов при преобразовании в тип int, то же самое происходит и при преобразовании в
число с плавающей точкой (float).
Сравнение чисел с плавающей точкой
Как отмечалось в предыдущем предупреждении, проверка чисел с плавающей точкой на равенство
даёт сомнительные результаты из-за ограничений внутреннего представления таких чисел,
однако PHP поддерживает способы сравнения чисел с плавающей точкой,
которые обходят эти ограничения.
Для сравнения чисел с плавающей точкой используется верхняя граница
относительной ошибки при округлении. Эта величина называется
машинной эпсилон или единицей округления (unit roundoff)
и представляет собой самую маленькую допустимую разницу при расчётах.
Числа $a и $b равны до 5-ти
знаков после точки.
Пример #1 Сравнение чисел с плавающей точкой
<?php
$a = 1.23456789;
$b = 1.23456780;
$epsilon = 0.00001;
if (abs($a - $b) < $epsilon) {
echo "true";
}
?>
NaN
Некоторые числовые операции могут возвращать значение, представляемое
константой NAN
. Данный результат означает неопределённое
или непредставимое значение в операциях с плавающей точкой. Любое строгое
или нестрогое сравнение данного значения с другим значением, кроме true
, включая его
самого, возвратит false
.
Так как NAN
представляет собой неограниченное количество
различных значений, то NAN
не следует сравнивать с
другими значениями, включая её саму. Вместо этого, для определения её наличия
необходимо использовать функцию is_nan().